/*
 * $Id$
 *
 * Copyright ( c ) 2014 XuNuo Corporation. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of XuNuo
 * Corporation ("Confidential Information").  You shall not disclose such
 * Confidential Information and shall use it only in accordance with the terms
 * of the license agreement you entered into with XuNuo Corporation or a XuNuo
 * authorized reseller (the "License Agreement"). XuNuo may make changes to the
 * Confidential Information from time to time. Such Confidential Information may
 * contain errors.
 *
 * EXCEPT AS EXPLICITLY SET FORTH IN THE LICENSE AGREEMENT, XuNuo DISCLAIMS ALL
 * WARRANTIES, COVENANTS, REPRESENTATIONS, INDEMNITIES, AND GUARANTEES WITH
 * RESPECT TO SOFTWARE AND DOCUMENTATION, WHETHER EXPRESS OR IMPLIED, WRITTEN OR
 * ORAL, STATUTORY OR OTHERWISE INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A
 * PARTICULAR PURPOSE. XuNuo DOES NOT WARRANT THAT END USER'S USE OF THE
 * SOFTWARE WILL BE UNINTERRUPTED, ERROR FREE OR SECURE.
 *
 * XuNuo SHALL NOT BE LIABLE TO END USER, OR ANY OTHER PERSON, CORPORATION OR
 * ENTITY FOR INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL
 * DAMAGES, OR DAMAGES FOR LOSS OF PROFITS, REVENUE, DATA OR USE, WHETHER IN AN
 * ACTION IN CONTRACT, TORT OR OTHERWISE, EVEN IF XuNuo HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES. XuNuo' TOTAL LIABILITY TO END USER SHALL NOT
 * EXCEED THE AMOUNTS PAID FOR THE XuNuo SOFTWARE BY END USER DURING THE PRIOR
 * TWELVE (12) MONTHS FROM THE DATE IN WHICH THE CLAIM AROSE.  BECAUSE SOME
 * STATES OR JURISDICTIONS DO NOT ALLOW LIMITATION OR EXCLUSION OF CONSEQUENTIAL
 * OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY TO END USER.
 *
 * Copyright version 2.0
 */
package com.th.supcom.pds.impl.service.adapter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.carefx.framework.exception.BusinessException;
import net.carefx.framework.translate.TranslatorManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.th.supcom.pds.domain.pojo.CpoeBasicFreqDetail;
import com.th.supcom.pds.domain.pojo.DeptVsDispensary;
import com.th.supcom.pds.domain.pojo.PhamBasicInfo;
import com.th.supcom.pds.domain.pojo.PhamDispensaryConfig;
import com.th.supcom.pds.external.api.AdapterCPOEExtService;
import com.th.supcom.pds.impl.common.enums.Cycle;
import com.th.supcom.pds.impl.common.enums.FreqIntervalUnitsEnum;
import com.th.supcom.pds.impl.manager.DeptVsDispensaryManager;
import com.th.supcom.pds.impl.manager.PhamInfoManager;
import com.th.supcom.pds.internal.api.config.PhamDispensaryConfigService;

/**
 * Pds药品摆药实现类
 * 
 * @author Zli
 */
public class AdapterCPOEExtServiceImpl implements AdapterCPOEExtService
{
    /** 日志记录器. */
    public static Logger s_logger = LoggerFactory.getLogger (AdapterCPOEExtService.class);
    private DeptVsDispensaryManager m_deptVsDispensaryManager;
    private PhamInfoManager m_phamInfoManager;
    private TranslatorManager m_translatorManager;
    private PhamDispensaryConfigService m_phamDispensaryConfigService;
    private static final String SPLIT_Y = "10";

    public void setTranslatorManager (TranslatorManager translatorManager)
    {

        m_translatorManager = translatorManager;
    }

    public void setPhamDispensaryConfigService (PhamDispensaryConfigService phamDispensaryConfigService)
    {

        m_phamDispensaryConfigService = phamDispensaryConfigService;
    }

    public void setDeptVsDispensaryManager (DeptVsDispensaryManager deptVsDispensaryManager)
    {

        m_deptVsDispensaryManager = deptVsDispensaryManager;
    }

    public void setPhamInfoManager (PhamInfoManager phamInfoManager)
    {

        m_phamInfoManager = phamInfoManager;
    }

    @Override
    public Map <String, Object> findDispensaryListByDeptCode (String hospitalArea, String clinicAreaId, String deptCode)
    {
        s_logger.debug ("进入findDispensaryListByDeptCode方法 入参：hospitalArea:clinicAreaId:deptCode", new Object[]
        { hospitalArea, clinicAreaId, deptCode });
        Map <String, Object> map = new HashMap <String, Object> ();
        verifyParmas (hospitalArea, clinicAreaId, deptCode);
        DeptVsDispensary deptVsDispensary = new DeptVsDispensary ();
        deptVsDispensary.setDeptCode (deptCode);
        List <DeptVsDispensary> deptVsDispensaryList = null;
        deptVsDispensaryList = queryPharmacyService (deptVsDispensary, deptVsDispensaryList);
        if (deptVsDispensaryList.isEmpty ())
        {
            return map;
        }
        getQueryResult (map, deptVsDispensaryList);
        return map;

    }

    /**
     * 对查询出来的数据进行处理
     * 
     * @param map
     * @param deptVsDispensaryList add by Zli
     */
    private void getQueryResult (Map <String, Object> map, List <DeptVsDispensary> deptVsDispensaryList)
    {
        try
        {
            for (DeptVsDispensary deptVsDispensary2 : deptVsDispensaryList)
            {
                // 判断药房是白班还是夜班
                PhamDispensaryConfig phamDispensaryConfig = m_phamDispensaryConfigService.getPhamDispensaryConfigByPhamDispensaryCode (deptVsDispensary2.getDispensary ());
                SimpleDateFormat df = new SimpleDateFormat ("HH:mm");
                Date startTime = null;
                Date endTime = null;
                String shiftType = null;
                Date currentTime = new Date ();
                String ct = df.format (currentTime);

                currentTime = df.parse (ct);
                startTime = df.parse (phamDispensaryConfig.getStartTime ());
                endTime = df.parse (phamDispensaryConfig.getEndTime ());

                // 找出对应班次的标志
                if (currentTime.before (endTime) || currentTime.after (startTime))
                {
                    shiftType = phamDispensaryConfig.getShiftType ();
                }
                // 挑选出优先级为1的药房
                if (deptVsDispensary2.getShift ().equals (shiftType) && deptVsDispensary2.getPrioriyt ().equals (1))
                    ;
                {
                    map.put ("dispensaryCode", deptVsDispensary2.getDispensary ());
                    map.put ("dispensaryName", deptVsDispensary2.getDispensaryName ());
                    break;
                }
            }
        }
        catch (ParseException e)
        {
            s_logger.error ("日期格式不正确");
        }
    }

    /**
     * 查询药房服务
     * 
     * @param deptVsDispensary
     * @param deptVsDispensaryList
     * @return add by Zli
     */
    private List <DeptVsDispensary> queryPharmacyService (DeptVsDispensary deptVsDispensary,
                                                          List <DeptVsDispensary> deptVsDispensaryList)
    {
        s_logger.debug ("查询药房服务，入参：deptVsDispensary:{},deptVsDispensaryList:{}",new Object[]{deptVsDispensary,deptVsDispensaryList});
        try
        {
            deptVsDispensaryList = m_deptVsDispensaryManager.findDeptVsDispensaryListByExample (deptVsDispensary);
        }
        catch (Exception e)
        {
            s_logger.error (e.getLocalizedMessage ());
            throw new BusinessException ("查询药房服务失败", e);
        }
        deptVsDispensaryList = m_translatorManager.translate (deptVsDispensaryList);
        return deptVsDispensaryList;
    }

    /**
     * 验证入参
     * 
     * @param deptCode
     * @param clinicAreaId add by Zli
     */
    private void verifyParmas (String hospitalArea, String clinicAreaId, String deptcode)
    {
        verifySingleParam (hospitalArea, "hospitalArea");
        verifySingleParam (clinicAreaId, "clinicAreaId");
        verifySingleParam (deptcode, "deptcode");
    }

    @Override   
    public List <Map <String, Object>> getOutpDispenseCount (List <Map <String, Object>> params)
    {
        s_logger.debug ("调用getOutpDispenseCount方法，入参：params:{}",new Object[]{params});
        List <Map <String, Object>> maps = new ArrayList <Map <String, Object>> ();
        if (params == null || params.isEmpty ())
        {
            throw new BusinessException ("集合为空");
        }

        for (Map <String, Object> map : params)
        {
            // 验证参数
            verifyMap (map);
            Map <String, Object> returnMap = new HashMap <String, Object> ();
            // 得到药品基本信息
            PhamBasicInfo basicInfo;
            // 判断药品是否可分割
            List <String> list=null;
            try
            {
                basicInfo = m_phamInfoManager.getPhamBasicInfoByMap (map);
                basicInfo = m_translatorManager.translate (basicInfo);
                list = m_phamInfoManager.findPhamBasicInfoSplitByMap (map);
            }
            catch (Exception e)
            {
                s_logger.error("入参:map:{}",new Object[]{map});
                throw new BusinessException ("查询药品基本信息出现异常"+e.getLocalizedMessage (),e);
            }
            boolean flag = false;
            if (!list.isEmpty ())
            {
                for (String string : list)
                {
                    if (SPLIT_Y.equals (string))
                    {
                        flag = true;
                        break;
                    }
                }
            }
            // 频次系数
            Double freqFactor = getFreqFactor (map);
            // 单日基本数量
            Double singleDayAmout = 0.0;
            String perMeiTty = map.get ("perMeiTty").toString ();
            String[] arr = perMeiTty.split (",");
            // 如果每天用量只给出一个值
            if (arr.length == 1)
            {
                singleDayAmout = Double.parseDouble (perMeiTty) / basicInfo.getDosePerUnit () * freqFactor;
            }
            else
            {
                for (String string : arr)
                {
                    if (flag)
                    {
                        singleDayAmout += Double.parseDouble (string) / basicInfo.getDosePerUnit ();
                    }
                    else
                    {
                        singleDayAmout += Math.ceil (Double.parseDouble (string) / basicInfo.getDosePerUnit ());
                    }
                }
            }
            int factor = Cycle.DAY.getEnumCode ().equals (Integer.parseInt (map.get ("cycleUnit").toString ())) ? 1
                                                                                                               : 30;
            Double totalAmout = Math.ceil (singleDayAmout * ((Integer) map.get ("cycleAmount")) * factor);
            Double packageAmount = Math.ceil (totalAmout / basicInfo.getPackageFactor ());
            returnMap.put ("Id", map.get ("Id"));
            returnMap.put ("phamStdCode", map.get ("phamStdCode"));
            returnMap.put ("totalAmout", totalAmout);
            returnMap.put ("totalAmoutUnit", basicInfo.getPhamUnit ());
            returnMap.put ("totalAmoutUnitName", basicInfo.getPhamUnitName ());
            returnMap.put ("packageAmount", packageAmount);
            returnMap.put ("packageUnit", basicInfo.getPackageUnit ());
            returnMap.put ("packageUnitName", basicInfo.getPackageUnitName ());
            returnMap.put ("pakageFactor", basicInfo.getPackageFactor ());
            returnMap.put ("singleDayAmout", singleDayAmout);
            returnMap.put ("singleDayUnit", basicInfo.getPhamUnit ());
            returnMap.put ("singleDayUnitName", basicInfo.getPhamUnitName ());
            maps.add (returnMap);
        }
        return maps;
    }

    private void verifyMap (Map <String, Object> map)
    {
        String Id = map.get ("Id") + "";
        String phamStdCode = map.get ("phamStdCode") + "";
        String freqCode = map.get ("freqCode") + "";
        Integer cycleAmount = (Integer) map.get ("cycleAmount");
        Integer cycleUnit = (Integer) map.get ("cycleUnit");
        String perMeiTty = map.get ("perMeiTty") + "";
        String meiUnit = map.get ("meiUnit") + "";
        verifySingleParam (Id, "Id");
        verifySingleParam (meiUnit, "meiUnit");
        verifySingleParam (phamStdCode, "phamStdCode");
        verifySingleParam (freqCode, "freqCode");
        verifySingleParam (cycleAmount, "cycleAmount");
        verifySingleParam (cycleUnit, "cycleUnit");
        verifySingleParam (perMeiTty, "perMeiTty");
    }

    private void verifySingleParam (Object obj, String key)
    {
        if (obj == null)
        {
            throw new BusinessException (key + "字段为空");
        }
    }

    /**
     * 得到频次系数
     * 
     * @param map
     * @return add by Zli
     */
    private Double getFreqFactor (Map <String, Object> map)
    {
        s_logger.debug ("调用getCpoeBasicFreqDetailByID方法,入参map:{}",new Object[]{map});
        Double freqFactor = 0.0;
        CpoeBasicFreqDetail cpoeBasicFreqDetail;
        try
        {
            cpoeBasicFreqDetail = m_phamInfoManager.getCpoeBasicFreqDetailByID (map.get ("freqCode")
                                                                                                    + "");
        }
        catch (Exception e)
        {
            s_logger.error("入参:map:{}",new Object[]{map});
           throw new BusinessException ("查询药品换算系数出现异常"+e.getLocalizedMessage (),e);
        }
        int interval = Integer.parseInt (cpoeBasicFreqDetail.getFreqInterval ());
        int freqCount = Integer.parseInt (cpoeBasicFreqDetail.getFreqCounter ());
        String freqUnits = cpoeBasicFreqDetail.getFreqIntervalUnits ();
        if (FreqIntervalUnitsEnum.Day.getEnumName ().equals (freqUnits))
        {
            freqFactor = (double) (freqCount / interval * FreqIntervalUnitsEnum.Day.getEnumCode ());
        }
        if (FreqIntervalUnitsEnum.Hour.getEnumName ().equals (freqUnits))
        {
            freqFactor = (double) (freqCount / interval * FreqIntervalUnitsEnum.Hour.getEnumCode ());
        }
        if (FreqIntervalUnitsEnum.Week.getEnumName ().equals (freqUnits))
        {
            freqFactor = (double) (freqCount / interval * FreqIntervalUnitsEnum.Week.getEnumCode ());
        }
        return freqFactor;
    }
}
